package com.example.demo.interview;

import org.assertj.core.util.DateUtil;

import java.util.*;

/**
 * @author Chenhoubo
 * @version v1.0
 * @date 2024/4/21 14:37
 * @Desc
 * 1、有一家超市，出售苹果和草莓。其中苹果 8 元/斤，草莓 13 元/斤。
 * 现在顾客 A 在超市购买了若干斤苹果和草莓，需要计算一共多少钱？
 * 请编写函数，对于 A 购买的水果斤数 (水果斤数为大于等于 0 的整数)，计算并返回所购买商品的总价。
 *
 * 2、超市增加了一种水果芒果，其定价为 20 元/斤。
 * 现在顾客 B 在超市购买了若干斤苹果、 草莓和芒果，需计算一共需要多少钱？
 * 请编写函数，对于 B 购买的水果斤数 (水果斤数为大于等于 0 的整数)，计算并返回所购买商品的总价。
 *
 * 3、超市做促销活动，草莓限时打 8 折。
 * 现在顾客 C 在超市购买了若干斤苹果、 草莓和芒果，需计算一共需要多少钱？
 * 请编写函数，对于 C 购买的水果斤数 (水果斤数为大于等于 0 的整数)，计算并返回所购买商品的总价。
 *
 * 4、促销活动效果明显，超市继续加大促销力度，购物满 100 减 10 块。
 * 现在顾客 D 在超市购买了若干斤苹果、 草莓和芒果，需计算一共需要多少钱？
 * 请编写函数，对于 D 购买的水果斤数 (水果斤数为大于等于 0 的整数)，计算并返回所购买商品的总价。
 * @since Interview
 */
public class Demo {
    //数据表
    public static final Map<Integer, Fruit> fruitMap = new HashMap<>();
    static {
        //key 为商品id，value 为商品信息
        fruitMap.put(1, new Fruit(1, "苹果", 8));
        fruitMap.put(2, new Fruit(2, "草莓", 13));
        fruitMap.put(3, new Fruit(3, "芒果", 20));
    }

    //优惠表
    public static final Map<Integer, Promotion> discountMap = new HashMap<>();
    static {
        //key 为优惠id，value 为优惠信息
        discountMap.put(1, new Promotion(1, "打折优惠", 8, 0, new Date(1871188131000L)));
        discountMap.put(2, new Promotion(2, "满减优惠", 10,100, new Date(1871188131000L)));
    }

    public static void main(String[] args) {
        // 顾客 A 购买了 1 斤苹果和 2 斤草莓
        List<BillItem> aBillItems = new ArrayList<>();
        aBillItems.add(new BillItem(1, 1, 0));
        aBillItems.add(new BillItem(2, 2, 0));
        Bill aBill = getBill("顾客 A",aBillItems,null);
        System.out.println(aBill);
        System.out.println("====================================");
        // 顾客 B 购买了 1 斤苹果、2 斤草莓和 3 斤芒果
        ArrayList<BillItem> billItems = new ArrayList<>();
        billItems.add(new BillItem(1, 1, 0));
        billItems.add(new BillItem(2, 2, 0));
        billItems.add(new BillItem(3, 3, 0));
        Bill bBill = getBill("顾客 B", billItems,null);
        System.out.println(bBill);
        System.out.println("====================================");
        // 顾客 C 购买了 1 斤苹果、2 斤草莓和 3 斤芒果,草莓限时打 8 折
        List<BillItem> cBillItems = new ArrayList<>();
        cBillItems.add(new BillItem(1, 1, 0));
        cBillItems.add(new BillItem(2, 6, 1));
        cBillItems.add(new BillItem(3, 3, 0));
        Bill cBill = getBill("顾客 C", cBillItems, null);
        System.out.println(cBill);
        System.out.println("====================================");
        // 顾客 D 购买了 1 斤苹果、2 斤草莓和 3 斤芒果,购物满 100 减 10 块
        List<BillItem> dBillItems = new ArrayList<>();
        dBillItems.add(new BillItem(1, 1, 0));
        dBillItems.add(new BillItem(2, 8, 1));
        dBillItems.add(new BillItem(3, 5, 0));
        Bill dBill = getBill("顾客 D", dBillItems, List.of(2));
        System.out.println(dBill);
    }


    /**
    * @Author  Chenhoubo
    * @Date   2024/4/21 15:01
    * @Param  customerName 顾客名称 billItems 购物清单 discountTypes 总账单优惠类型
     * @since Interview
    */
    private static Bill getBill(String customerName, List<BillItem> billItems, List<Integer> discountTypes) {
        Bill bill = new Bill();
        bill.discountAmount = 0;
        for (BillItem item : billItems) {
            item.total = item.price * item.count;
            item.discountAmount = 0;
            Promotion promotion = discountMap.get(item.discountType);
            if (promotion != null && promotion.expireTime != null && promotion.expireTime.after(DateUtil.now())) {
                if (promotion.type == 1) {
                    item.discountAmount = item.total * (10-promotion.amount) / 10;
                } else if (promotion.type == 2 && item.total >= promotion.threshold) {
                    item.discountAmount = promotion.amount;
                }
            }
            item.total -= item.discountAmount;
            bill.addItem(item);
        }
        if (discountTypes != null) {
            for (Integer discountType : discountTypes) {
                Promotion promotion = discountMap.get(discountType);
                if (promotion != null && promotion.expireTime != null && promotion.expireTime.after(DateUtil.now())) {
                    if (promotion.type == 1) {
                        bill.discountAmount = bill.total * (10-promotion.amount) / 10;
                    } else if (promotion.type == 2 && bill.total >= promotion.threshold) {
                        bill.discountAmount = promotion.amount;
                    }
                }
            }
            bill.total -= bill.discountAmount;
            if(bill.total < 0){
                bill.total = 0;
            }
        }
        bill.customerName = customerName;
        return bill;
    }

    //账单项
    public static class BillItem{
        //商品id
        private int id;
        //商品名称
        private String name;
        //单价
        private int price;
        //活动优惠类型（1：打折优惠，2：满减优惠）
        private int discountType;
        //活动优惠金额
        private int discountAmount;
        //购买数量
        private int count;
        //总价
        private int total;

        public BillItem(int id, int count, int discountType) {
            Fruit fruit = fruitMap.get(id);
            if(fruit == null){
                throw new RuntimeException("商品不存在");
            }
            if(count < 0){
                throw new RuntimeException("商品数量不能小于0");
            }
            this.id = id;
            this.count = count;
            this.discountType = discountType;
            this.name = fruit.getName();
            this.price = fruit.getPrice();
        }
    }

    //账单
    public static class Bill{
        //顾客id
        private int customerId;
        //顾客名称
        private String customerName;
        //商品列表
        private List<BillItem> items = new ArrayList<>();
        //总账单-活动优惠类型（1：打折优惠，2：满减优惠）
        private int discountType;
        //总账单-活动优惠金额
        private int discountAmount;
        //共优惠
        private int totalDiscountAmount;
        //总价
        private int total;

        public void addItem(BillItem item){
            items.add(item);
            totalDiscountAmount += item.discountAmount;
            total += item.total;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(customerName).append("---账单如下：").append("\n");
            for (BillItem item : items) {
                sb.append(item.name).append("(").append(item.price).append(")")
                        .append(" x ").append(item.count).append(" - ").append(item.discountAmount)
                        .append(" = ").append(item.total).append("\n");
            }
            sb.append("活动优惠：").append(totalDiscountAmount).append("\n");
            sb.append("总账单优惠：").append(discountAmount).append("\n");
            sb.append("共优惠：").append(totalDiscountAmount+discountAmount).append("\n");
            sb.append("总价：").append(total);
            return sb.toString();
        }
    }

    //优惠表
    public static class Promotion{
        //优惠类型 1：打折优惠，2：满减优惠
        private int type;
        //标题
        private String title;
        //优惠金额 type=1 为折扣，type=2 为减免金额
        private int amount;
        //优惠门槛 type=2 为满减门槛
        private int threshold;
        //有效期--限时优惠
        private Date expireTime;

        public Promotion(int type, String title, int amount, int threshold, Date expireTime) {
            this.type = type;
            this.title = title;
            this.amount = amount;
            this.threshold = threshold;
            this.expireTime = expireTime;
        }
    }

    //物品表-水果表
    public static class Fruit {
        //id
        private int id;
        //名称
        private String name;
        //单价
        private int price;

        public Fruit(int id, String name, int price) {
            this.id = id;
            this.name = name;
            this.price = price;
        }

        public int getPrice() {
            return price;
        }

        public void setPrice(int price) {
            this.price = price;
        }

        public String getName() {
            return name;
        }

        public void set(String name) {
            this.name = name;
        }
    }

}
